﻿using System;

namespace FFACETools
{
    public partial class FFACE
    {
        /// <summary>
        /// Wrapper class for item information from FFACE
        /// </summary>
        public class ItemTools
        {
            #region Constants

            /// <summary>
            /// Argument exception for inventory item calls
            /// </summary>
            private const string INVENTORY_RANGE = "Index must be between 1 and 80";

            #endregion

            #region Classes

            /// <summary>
            /// Class container for Inventory Items
            /// </summary>
            public class InventoryItem
            {
                #region Constructors

                public InventoryItem(ushort iD, byte index, uint count, uint flag, uint price, ushort extra)
                {
                    ID = iD;
                    Index = index;
                    Count = count;
                    Flag = flag;
                    Price = price;
                    Extra = extra;
                }

                public InventoryItem(ushort iD, byte index, uint count)
                {
                    ID = iD;
                    Index = index;
                    Count = count;
                }

                #endregion

                #region Members

                /// <summary>
                /// ID of the item
                /// </summary>
                public ushort ID { get; set; }

                /// <summary>
                /// Index of the item
                /// </summary>
                public byte Index { get; set; }

                /// <summary>
                /// Count of the item
                /// </summary>
                public uint Count { get; set; }

                /// <summary>
                /// Flags on the item
                /// </summary>
                public uint Flag { get; set; }

                /// <summary>
                /// Price of the item
                /// </summary>
                public uint Price { get; set; }

                /// <summary>
                /// Extra information about the item
                /// </summary>
                public ushort Extra { get; set; }

                #endregion

            } // @ public class InventoryItem

            #endregion

            #region Constructor

            /// <summary>
            /// Constructor
            /// </summary>
            /// <param name="instanceID">Instance ID generated by FFACE</param>
            public ItemTools(int instanceID)
            {
                _InstanceID = instanceID;

            } // @ public InventoryWrapper(int instanceID)

            #endregion

            #region Members

            /// <summary>
            /// Instance ID generated by FFACE
            /// </summary>
            private int _InstanceID { get; set; }

            /// <summary>
            /// Maximum amount of inventory slots player has
            /// </summary>
            public short InventoryMax
            {
                get { return GetInventoryMax(_InstanceID); }

            } // @ public short Max

            /// <summary>
            /// Maximum amount of safe slots player has
            /// </summary>
            public short SafeMax
            {
                get { return GetSafeMax(_InstanceID); }

            } // @ public short SafeMax

            /// <summary>
            /// Maximum amount of storage slots player has
            /// </summary>
            public short StorageMax
            {
                get { return GetStorageMax(_InstanceID); }

            } // @ public short StorageMax

            /// <summary>
            /// Maximum amount of temporary slots player has
            /// </summary>
            public short TemporaryMax
            {
                get { return GetTempMax(_InstanceID); }

            } // @ public short TemporaryMax

            /// <summary>
            /// Maximum amount of locker slots player has
            /// </summary>
            public short LockerMax
            {
                get { return GetLockerMax(_InstanceID); }

            } // @ public short LockerMax

            /// <summary>
            /// Maximum amount of satchel slots player has
            /// </summary>
            public short SatchelMax
            {
                get { return GetSatchelMax(_InstanceID); }

            } // @ public short SatchelMax

            /// <summary>
            /// Inventory slots in use
            /// </summary>
            public short InventoryCount
            {
                get
                {
                    // calculate amount of slots are not empty
                    short count = 0;

                    for (byte i = 1; i <= 80; i++)
                       if (!GetInventoryItem(i).ID.Equals(0))
                            count++;

                    return count;
                }

            } // @ public short InventoryCount

            /// <summary>
            /// Name of the selected item
            /// </summary>
            public string SelectedItemName
            {
                get
                {
                    // get the string from FFACE
                    int size = 20;
                    byte[] buffer = new byte[20];
                    GetSelectedItemName(_InstanceID, buffer, ref size);

                    // convert to a string
                    return System.Text.Encoding.ASCII.GetString(buffer, 0, size - 1);
                }
            } // @ public string SelectedItemName

            /// <summary>
            /// Index of the selected item
            /// </summary>
            public short SelectedItemIndex
            {
                get { return GetSelectedItemIndex(_InstanceID); }

            } // @ public short SelectedItemIndex

            /// <summary>
            /// Place in inventory (0 -> max inventory)
            /// </summary>
            public int SelectedItemNum
            {
                get { return GetSelectedItemNum(_InstanceID); }

            } // @ public short SelectedItemNum

            #endregion

            #region Methods

            #region Methods relating to inventory

            /// <summary>
            /// Will get an inventory item ID by index
            /// </summary>
            /// <param name="index">Index of the item in your inventory</param>
            public int GetInventoryItemIDByIndex(byte index)
            {
                if (1 > index || 80 < index)
                    throw new ArgumentOutOfRangeException(INVENTORY_RANGE);

                return GetInventoryItem(index).ID;

            } // @ public int GetItemIDByIndex(short index)

            /// <summary>
            /// The amount of passed items you have in your inventory
            /// </summary>
            /// <param name="iD">ID of the item to count</param>
            public uint GetInventoryItemCount(ushort iD)
            {
                uint count = 0;

                for (byte i = 1; i <= 80; i++)
                {
                    InventoryItem item = GetInventoryItem(i);

                    if (item.ID.Equals(iD))
                        count += item.Count;

                } // @ for (short i = 0; i < 80; i++)

                return count;

            } // @ public int ItemCount(short ID)

            /// <summary>
            /// Gets information about an item from your inventory
            /// </summary>
            /// <param name="index">Index of the item</param>
            public InventoryItem GetInventoryItem(int index)
            {
                // done this way because INVENTORYITEM is a private structure
                INVENTORYITEM item = FFACE.GetInventoryItem(_InstanceID, index);
                return new InventoryItem(item.ID, item.Index, item.Count, item.Flag, item.Price, item.Extra);

            } // @ public INVENTORYITEM GetInventoryItem(int index)

            #endregion

            /// <summary>
            /// Gets information about an item from your safe
            /// </summary>
            /// <param name="index">Index of the item</param>
            public InventoryItem GetSafeItem(ushort index)
            {
                if (1 > index || 80 < index)
                    throw new ArgumentOutOfRangeException(INVENTORY_RANGE);

                // done this way because INVENTORYITEM is a private structure
                INVENTORYITEM item = FFACE.GetSafeItem(_InstanceID, (byte)index);
                return new InventoryItem(item.ID, item.Index, item.Count, item.Flag, item.Price, item.Extra);

            } // @ public INVENTORYITEM GetSafeItem(byte index)

            /// <summary>
            /// Gets information about an item from your storage
            /// </summary>
            /// <param name="index">Index of teh item</param>
            public InventoryItem GetStorageItem(int index)
            {
                // done this way because INVENTORYITEM is a private structure
                INVENTORYITEM item = FFACE.GetStorageItem(_InstanceID, index);
                return new InventoryItem(item.ID, item.Index, item.Count, item.Flag, item.Price, item.Extra);

            } // @ public INVENTORYITEM GetStorageItem(int index)

            /// <summary>
            /// Gets information about an item from your locker
            /// </summary>
            /// <param name="index">Index of the item</param>
            public InventoryItem GetLockerItem(ushort index)
            {
                if (1 > index || 80 < index)
                    throw new ArgumentOutOfRangeException(INVENTORY_RANGE);

                // done this way because INVENTORYITEM is a private structure
                INVENTORYITEM item = FFACE.GetLockerItem(_InstanceID, (byte)index);
                return new InventoryItem(item.ID, item.Index, item.Count, item.Flag, item.Price, item.Extra);

            } // @ public InventoryItem GetLockerItem(ushort index)

            /// <summary>
            /// Gets information about a temporary item
            /// </summary>
            /// <param name="index">Index of the item</param>
            public InventoryItem GetTempItem(ushort index)
            {
                if (1 > index || 80 < index)
                    throw new ArgumentOutOfRangeException(INVENTORY_RANGE);

                // done this way because INVENTORYITEM is a private structure
                INVENTORYITEM item = FFACE.GetTempItem(_InstanceID, (byte)index);
                return new InventoryItem(item.ID, item.Index, item.Count, item.Flag, item.Price, item.Extra);

            } // @ public InventoryItem GetLockerItem(ushort index)

            /// <summary>
            /// Gets information about an item from your Satchel
            /// </summary>
            /// <param name="index">Index of the item</param>
            public InventoryItem GetSatchelItem(ushort index)
            {
                if (1 > index || 80 < index)
                    throw new ArgumentOutOfRangeException(INVENTORY_RANGE);

                // done this way because INVENTORYITEM is a private structure
                INVENTORYITEM item = FFACE.GetLockerItem(_InstanceID, (byte)index);
                return new InventoryItem(item.ID, item.Index, item.Count, item.Flag, item.Price, item.Extra);

            } // @ public InventoryItem GetLockerItem(ushort index)

            /// <summary>
            /// The count of an item by index
            /// </summary>
            /// <param name="index">Index of the item</param>
            public uint GetItemCountByIndex(byte index)
            {
                return GetInventoryItem(index).Count;

            } // @ public byte GetItemCountByIndex(byte index)

            /// <summary>
            /// The count of an item in a specific equipment slot
            /// </summary>
            /// <param name="slot">Slot to count</param>
            public uint GetEquippedItemCount(EquipSlot slot)
            {
                return GetInventoryItem(GetEquippedItemIndex(slot)).Count;

            } // @ public byte GetEquippedItemCount(EquipSlot slot)

            /// <summary>
            /// Gets information about an item currently in the treasure pool
            /// </summary>
            /// <param name="index">Index of the treasure item</param>
            public TREASUREITEM GetTreasureItem(byte index)
            {
                return FFACE.GetTreasureItem(_InstanceID, index);

            } // @ public TREASUREITEM GetTrasureItem(byte index)

            /// <summary>
            /// Gets the item id for passed equipment slot
            /// </summary>
            /// <param name="slot">Slot to get the ID for</param>
            public ushort GetEquippedItemID(EquipSlot slot)
            {
                return GetInventoryItem(GetEquippedItemIndex(slot)).ID;

            } // @ public short GetEquippedItemID(EquipSlot slot)

            /// <summary>
            /// Gets the index of an item for the passed equipment slot
            /// </summary>
            /// <param name="slot">Slot to get the index for</param>
            public byte GetEquippedItemIndex(EquipSlot slot)
            {
                return FFACE.GetEquippedItemIndex(_InstanceID, slot);

            } // @ public byte GetEquippedItemIndex(EquipSlot slot)

            #endregion

        } // @ class ItemTools
    } // @ public partial class FFACE
}
